package com.hospital.hospitalsystem.modules.medicine.biz;
import com.github.pagehelper.PageHelper;
import com.hospital.hospitalsystem.base.PageData;
import com.hospital.hospitalsystem.modules.base.biz.UploadBiz;
import com.hospital.hospitalsystem.modules.base.dto.DeleteReq;
import com.hospital.hospitalsystem.modules.doctor.dao.entity.PrescriptionEntity;
import com.hospital.hospitalsystem.modules.doctor.dto.PrescriptionReq;
import com.hospital.hospitalsystem.modules.doctor.service.PrescriptionService;
import com.hospital.hospitalsystem.modules.hospital.dto.DepartmentRsp;
import com.hospital.hospitalsystem.modules.login.dao.entity.UserEntity;
import com.hospital.hospitalsystem.modules.login.dao.entity.UserMessageEntity;
import com.hospital.hospitalsystem.modules.login.dto.EmailEntityExt;
import com.hospital.hospitalsystem.modules.login.service.UserMessageService;
import com.hospital.hospitalsystem.modules.login.service.UserService;
import com.hospital.hospitalsystem.modules.medicine.dao.entity.HospitalMedicalEntity;
import com.hospital.hospitalsystem.modules.medicine.dao.entity.HospitalMedicalHistoryEntity;
import com.hospital.hospitalsystem.modules.medicine.dto.*;
import com.hospital.hospitalsystem.modules.medicine.service.HospitalMedicalHistoryService;
import com.hospital.hospitalsystem.modules.medicine.service.HospitalMedicalService;
import com.hospital.hospitalsystem.modules.user.dao.entity.ShoppingCartEntity;
import com.hospital.hospitalsystem.modules.user.service.BookService;
import com.hospital.hospitalsystem.modules.user.service.ShoppingCartService;
import com.hospital.hospitalsystem.utils.SendEmailUtils;
import kotlin.jvm.internal.PackageReference;
import org.apache.catalina.User;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.Sqls;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author qiancheng@cqxyy.net
 * @date 2023/4/4
 */
@Service
public class HospitalMedicalBiz {

    @Autowired
    private HospitalMedicalService hospitalMedicalService;

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private HospitalMedicalHistoryBiz hospitalMedicalHistoryBiz;

    @Autowired
    private SendEmailUtils sendEmailUtils;

    @Autowired
    private UserService userService;

    @Autowired
    private HospitalMedicalHistoryService hospitalMedicalHistoryService;

    @Autowired
    private UserMessageService userMessageService;

    @Autowired
    private PrescriptionService prescriptionService;

    @Autowired
    private BookService bookService;

    @Autowired
    private HospitalMedicalBiz hospitalMedicalBiz;

    @Autowired
    private UploadBiz uploadBiz;
    /**
     * 添加药品信息
     * @param req
     */
    public void addMedical(HospitalMedicalReq req,String operateUuid) {
        HospitalMedicalEntity hospitalMedicalEntity = new HospitalMedicalEntity();
        Example example = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("hospitalUuid",req.getHospitalUuid());
        criteria.andEqualTo("name",req.getName());
        if (hospitalMedicalService.selectByExample(example).size() > 0) {
            throw new RuntimeException("药品名称重复");
        }
        BeanUtils.copyProperties(req,hospitalMedicalEntity);
        hospitalMedicalEntity.setIssell(req.getIsSell());
        hospitalMedicalEntity.setIsotc(req.getIsOTC());
        hospitalMedicalEntity.setReserveCount(req.getCount());
        hospitalMedicalEntity.setMedicalUuid(UUID.randomUUID().toString());
        hospitalMedicalService.insertSelective(hospitalMedicalEntity);
        //写入日志表
        HospitalMedicalHistoryReq reqHistory = new HospitalMedicalHistoryReq();
        reqHistory.setHospitalUuid(req.getHospitalUuid());
        reqHistory.setType(1);
        reqHistory.setOperateUuid(operateUuid);
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("创建新药品条目:");
        stringBuffer.append(req.getName());
        stringBuffer.append(" 初始化库存:" + req.getCount() + " ");
        stringBuffer.append("价格:" + req.getPrice() + " ");
        stringBuffer.append("单位:" + returnUnit(req.getUnit()) + " ");
        stringBuffer.append("种类:" + returnType(req.getType()) + " ");
        stringBuffer.append("类型:" + returnIsOTC(req.getIsOTC()) + " ");
        stringBuffer.append(returnIsSell(req.getIsSell()));
        reqHistory.setMsg(stringBuffer.toString());
        hospitalMedicalHistoryBiz.addMsg(reqHistory);
    }

    /**
     *
     * @param req 删除药品信息
     */
    @Transactional
    public void deleteMedical(HospitalMedicalReq req,String operateUuid) {
        Example exampleHospitalMedical = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteriaHospitalMedical = exampleHospitalMedical.createCriteria();
        criteriaHospitalMedical.andEqualTo("hospitalUuid",req.getHospitalUuid());
        criteriaHospitalMedical.andEqualTo("medicalUuid",req.getMedicalUuid());
        HospitalMedicalEntity hospitalMedicalEntity = hospitalMedicalService.selectByExample(exampleHospitalMedical).get(0);

        //删除图片
        DeleteReq deleteReq = new DeleteReq();
        deleteReq.setBucketName("hospital-medical-picture");
        List<String> list = new ArrayList<>();
        list.add(hospitalMedicalEntity.getPictureName());
        deleteReq.setObjectName(list);
        uploadBiz.delete(deleteReq);

        Example exampleShoppingCart = new Example(ShoppingCartEntity.class);
        Example.Criteria criteriaShoppingCart = exampleShoppingCart.createCriteria();
        criteriaShoppingCart.andEqualTo("medicalUuid",req.getMedicalUuid());
        List<String> userUuids = shoppingCartService.selectByExample(exampleShoppingCart).stream().
                filter(distinctByKey(ShoppingCartEntity::getUserUuid)).map(s -> s.getUserUuid()).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(userUuids)) {
            Example exampleUser = new Example(UserEntity.class);
            Example.Criteria criteriaUser = exampleUser.createCriteria();
            criteriaUser.andIn("uuid",userUuids);
            criteriaUser.andEqualTo("ext",null);
            List<UserEntity> users = userService.selectByExample(exampleUser).stream().collect(Collectors.toList());
            users.forEach(user -> {
                EmailEntityExt emailEntityExt = new EmailEntityExt();
                emailEntityExt.setEmail(user.getAccount());
                emailEntityExt.setData("尊敬的用户您好，你购物车中的" + hospitalMedicalEntity.getName() + "药品已被下架");
                sendEmailUtils.sendEmails(emailEntityExt);
            });
            shoppingCartService.deleteByExample(exampleShoppingCart);
        }

        //写入日志表
        HospitalMedicalHistoryReq reqHistory = new HospitalMedicalHistoryReq();
        reqHistory.setHospitalUuid(req.getHospitalUuid());
        reqHistory.setType(3);
        hospitalMedicalService.deleteByExample(exampleHospitalMedical);
        reqHistory.setOperateUuid(operateUuid);
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("删除药品条目:");
        stringBuffer.append(hospitalMedicalEntity.getName());
        reqHistory.setMsg(stringBuffer.toString());
        hospitalMedicalHistoryBiz.addMsg(reqHistory);
    }

    /**
     * 根据uuid查询
     * @param req
     * @return
     */
    public HospitalMedicalRsp getOneMedical(HospitalMedicalReq req) {
        Example exampleHospitalMedical = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteriaHospitalMedical = exampleHospitalMedical.createCriteria();
        criteriaHospitalMedical.andEqualTo("hospitalUuid",req.getHospitalUuid());
        criteriaHospitalMedical.andEqualTo("medicalUuid",req.getMedicalUuid());
        HospitalMedicalEntity hospitalMedicalEntity = hospitalMedicalService.selectByExample(exampleHospitalMedical).get(0);
        HospitalMedicalRsp hospitalMedicalRsp = new HospitalMedicalRsp();
        BeanUtils.copyProperties(hospitalMedicalEntity,hospitalMedicalRsp);
        hospitalMedicalRsp.setIsOTC(hospitalMedicalEntity.getIsotc());
        hospitalMedicalRsp.setIsSell(hospitalMedicalEntity.getIssell());
        return hospitalMedicalRsp;
    }

    /**
     * 更新药品信息
     * @param req
     */
    public void updateMedical(HospitalMedicalReq req,String operateUuid) {
        Example exampleHospitalMedical = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteriaHospitalMedical = exampleHospitalMedical.createCriteria();
        criteriaHospitalMedical.andEqualTo("hospitalUuid",req.getHospitalUuid());
        criteriaHospitalMedical.andEqualTo("medicalUuid",req.getMedicalUuid());
        HospitalMedicalEntity compare = hospitalMedicalService.selectByExample(exampleHospitalMedical).get(0);

        HospitalMedicalEntity hospitalMedicalEntity = new HospitalMedicalEntity();
        hospitalMedicalEntity.setCount(req.getCount());
        hospitalMedicalEntity.setIssell(req.getIsSell());
        hospitalMedicalEntity.setName(req.getName());
        hospitalMedicalEntity.setPicture(req.getPicture());
        hospitalMedicalEntity.setPictureName(req.getPictureName());
        hospitalMedicalEntity.setIsotc(req.getIsOTC());
        hospitalMedicalEntity.setType(req.getType());
        hospitalMedicalEntity.setUnit(req.getUnit());
        if (compare.getCount() - compare.getReserveCount() <= req.getCount()) {
            hospitalMedicalEntity.setReserveCount(compare.getReserveCount() - (compare.getCount() - req.getCount()));
        } else {
            throw new RuntimeException("预留库存不允许为负数");
        }
        hospitalMedicalService.updateByExampleSelective(hospitalMedicalEntity,exampleHospitalMedical);

        //写入日志表
        HospitalMedicalHistoryReq reqHistory = new HospitalMedicalHistoryReq();
        reqHistory.setHospitalUuid(req.getHospitalUuid());
        reqHistory.setType(2);
        reqHistory.setOperateUuid(operateUuid);
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("更新药品条目:" + req.getName() + " ");
        if (compare.getCount() != req.getCount()) {
            stringBuffer.append("更新药品数量:" + req.getCount() + " ");
        }
        if (compare.getIsotc() != req.getIsOTC()) {
            stringBuffer.append("更新药品类型:" + returnIsOTC(req.getIsOTC()) + " ");
        }
        if (compare.getIssell() != req.getIsSell()) {
            stringBuffer.append("更新为" + returnIsSell(req.getIsSell()) + " ");
        }
        if (!compare.getPicture().equals(req.getPicture())) {
            stringBuffer.append("更新药品图片");
        }
        if (compare.getPrice().compareTo(req.getPrice()) != 0) {
            stringBuffer.append("更新药品单价:" + req.getPrice() + " ");
        }
        if (compare.getType() != req.getType()) {
            stringBuffer.append("更新药品种类:" + returnType(req.getType()));
        }
        if (compare.getUnit() != req.getUnit()) {
            stringBuffer.append("更新单位:" + returnUnit(req.getUnit()));
        }
        reqHistory.setMsg(stringBuffer.toString());
        hospitalMedicalHistoryBiz.addMsg(reqHistory);
    }

    /**
     * 获取药品信息
     * @param req
     * @return
     */
    public PageData<HospitalMedicalRsp> getMedical(HospitalMedicalListReq req) {
        Example exampleHospitalMedical = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteriaHospitalMedical = exampleHospitalMedical.createCriteria();
        criteriaHospitalMedical.andEqualTo("hospitalUuid",req.getHospitalUuid());
        if (StringUtils.isNotBlank(req.getName())) {
            criteriaHospitalMedical.andLike("name","%" + req.getName() + "%");
        }
        if (CollectionUtils.isNotEmpty(req.getIsOTC())) {
            criteriaHospitalMedical.andIn("isotc",req.getIsOTC());
        }
        if (req.getType() != null) {
            criteriaHospitalMedical.andEqualTo("type",req.getType());
        }
        if (req.getIsSell() != null) {
            criteriaHospitalMedical.andEqualTo("issell",req.getIsSell());
        }
        exampleHospitalMedical.orderBy("count").asc();
        com.github.pagehelper.Page<DepartmentRsp> page = PageHelper.startPage(
                req.getCurrentPage(), req.getPageSize()
        );
        List<HospitalMedicalRsp> list = hospitalMedicalService.selectByExample(exampleHospitalMedical).stream().map(item ->{
            HospitalMedicalRsp hospitalMedicalRsp = new HospitalMedicalRsp();
            BeanUtils.copyProperties(item,hospitalMedicalRsp);
            hospitalMedicalRsp.setIsSell(item.getIssell());
            hospitalMedicalRsp.setIsOTC(item.getIsotc());
            return hospitalMedicalRsp;
        }).collect(Collectors.toList());
        int longs = ((Number) page.getTotal()).intValue();
        PageData<HospitalMedicalRsp> pageData = PageData.of(list,page.getPageNum(),page.getPageSize(),longs);
        return pageData;
    }

    /**
     * 根据uuid入库药品
     * @param req
     */
    public void storageMedical(HospitalMedicalReq req,String operateUuid) {
        Example exampleMedical = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteriaMedical = exampleMedical.createCriteria();
        criteriaMedical.andEqualTo("hospitalUuid",req.getHospitalUuid());
        criteriaMedical.andEqualTo("medicalUuid",req.getMedicalUuid());
        HospitalMedicalEntity hospitalMedicalEntity = hospitalMedicalService.selectByExample(exampleMedical).get(0);
        hospitalMedicalEntity.setCount(hospitalMedicalEntity.getCount() + req.getCount());
        hospitalMedicalEntity.setReserveCount(hospitalMedicalEntity.getReserveCount() + req.getCount());
        hospitalMedicalService.updateByExampleSelective(hospitalMedicalEntity,exampleMedical);

        //写入日志表
        HospitalMedicalHistoryReq reqHistory = new HospitalMedicalHistoryReq();
        reqHistory.setHospitalUuid(req.getHospitalUuid());
        reqHistory.setType(5);
        reqHistory.setOperateUuid(operateUuid);
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("入库" + hospitalMedicalEntity.getName() + "药品");
        stringBuffer.append(" 数量:" + req.getCount() + returnUnit(hospitalMedicalEntity.getUnit()));
        stringBuffer.append(" 现有库存:" + hospitalMedicalEntity.getCount() + returnUnit((hospitalMedicalEntity.getUnit())));
        reqHistory.setMsg(stringBuffer.toString());
        hospitalMedicalHistoryBiz.addMsg(reqHistory);
    }

    public String returnIsOTC (Integer otc) {
        switch (otc) {
            case 1:
                return "处方药";
            case 2:
                return "甲类非处方药";
            case 3:
                return "乙类非处方药";
            case 4:
                return "既是处方又是非处方药";
            default:
                return "";
        }
    }
    private String returnIsSell(Integer isSell) {
        switch (isSell) {
            case 1:
                return "可以出售";
            case 2:
                return "禁止出售";
            default:
                return "";
        }
    }
    public String returnUnit(Integer unit) {
        switch (unit) {
            case 1:
                return "盒";
            case 2:
                return "瓶";
            case 3:
                return "袋";
            case 4:
                return "克";
            case 5:
                return "支";
            case 6:
                return "粒";
            default:
                return "";
        }
    }
    private String returnType(Integer type) {
        switch (type) {
            case 1:
                return "中药";
            case 2:
                return "西药";
            default:
                return "";
        }
    }

    // 根据指定的属性去重
    public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    /**
     * 库存检查
     * @param req
     * @return
     */
    public List<CheckStorageRsp> checkStorage(CheckStorageReq req) {
        List<CheckStorageRsp> result = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(req.getList())) {
            List<CheckStorageRsp> list = hospitalMedicalService.checkStorage(req);
            req.getList().forEach(item -> {
                list.forEach(tmp -> {
                    if (item.getHospitalUuid().equals(tmp.getHospitalUuid()) && item.getMedicalUuid().equals(tmp.getMedicalUuid()) && item.getCount() != null) {
                        if (tmp.getReserveCount() < item.getCount()) {
                            result.add(tmp);
                        }
                    }
                });
            });
        }
        return result;
    }

    /**
     * 根据药方出库药品
     * @param req
     */
    public void prescriptionOut(PrescriptionOutReq req) {
        Example exampleMedical = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteriaMedical = exampleMedical.createCriteria();
        if (CollectionUtils.isNotEmpty(req.getList())) {
            List<String> medicalUuids = req.getList().stream().map(s->s.getMedicalUuid()).collect(Collectors.toList());
            criteriaMedical.andIn("medicalUuid",medicalUuids);
        }
        criteriaMedical.andEqualTo("hospitalUuid",req.getHospitalUuid());
        Map<String,HospitalMedicalEntity> map = hospitalMedicalService.selectByExample(exampleMedical).stream().
                collect(Collectors.toMap(s->s.getMedicalUuid(),s->s));
        Example exampleUser = new Example(UserMessageEntity.class);
        Example.Criteria criteriaUser = exampleUser.createCriteria();
        criteriaUser.andEqualTo("uuid",req.getUserUuid());
        UserMessageEntity userMessageEntity = userMessageService.selectByExample(exampleUser).get(0);
        req.getList().forEach(item -> {
            HospitalMedicalHistoryEntity hospitalMedicalHistoryEntity = new HospitalMedicalHistoryEntity();
            hospitalMedicalHistoryEntity.setHospitalUuid(req.getHospitalUuid());
            hospitalMedicalHistoryEntity.setOperateUuid(req.getOperatorUuid());
            hospitalMedicalHistoryEntity.setType(4);
            hospitalMedicalHistoryEntity.setMsg("出库药品:" + map.get(item.getMedicalUuid()).getName() + " 数量:" +
                    item.getCount() + hospitalMedicalBiz.returnUnit(map.get(item.getMedicalUuid()).getUnit()) + " " + "类型:药方出库 " +
                    "患者:" + userMessageEntity.getName());
            hospitalMedicalHistoryService.insertSelective(hospitalMedicalHistoryEntity);

            HospitalMedicalEntity hospitalMedicalEntity = new HospitalMedicalEntity();
            hospitalMedicalEntity.setCount(map.get(item.getMedicalUuid()).getCount() - item.getCount());
            hospitalMedicalEntity.setReserveCount(map.get(item.getMedicalUuid()).getReserveCount() - item.getCount());
            Example exampleMedicals = new Example(HospitalMedicalEntity.class);
            Example.Criteria criteriaMedicals = exampleMedicals.createCriteria();
            criteriaMedicals.andEqualTo("hospitalUuid",req.getHospitalUuid());
            criteriaMedicals.andEqualTo("medicalUuid",item.getMedicalUuid());
            hospitalMedicalService.updateByExampleSelective(hospitalMedicalEntity,exampleMedicals);
        });
        Example examplePrescription = new Example(PrescriptionEntity.class);
        Example.Criteria criteriaPrescription = examplePrescription.createCriteria();
        criteriaPrescription.andEqualTo("prescriptionUuid",req.getPrescriptionUuid());
        PrescriptionEntity prescriptionEntity = new PrescriptionEntity();
        prescriptionEntity.setStatus(2);
        prescriptionService.updateByExampleSelective(prescriptionEntity,examplePrescription);
    }

    /**
     * 查看药方(仅限当日)
     * @param req
     * @return
     */
    public List<ShowPrescriptionRsp> showPrescription(ShowPrescriptionReq req) {
        SimpleDateFormat dfDate = new SimpleDateFormat("yyyy-MM-dd");
        Date nowDate = new Date();
        req.setNowDate(dfDate.format(nowDate));
        List<ShowPrescriptionRsp> list = bookService.showPrescription(req);
        return list;
    }

    /**
     * 完成抓药
     * @param req
     */
    public void finish(PrescriptionReq req) {
        Example example = new Example(PrescriptionEntity.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("prescriptionUuid",req.getPrescriptionUuid());
        PrescriptionEntity prescriptionEntity = new PrescriptionEntity();
        prescriptionEntity.setStatus(3);
        prescriptionService.updateByExampleSelective(prescriptionEntity,example);
    }
}
